/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { cloneDeep } from '@baize/wdk';
import { HvigorConfigLoader, hvigorCore, Project, ToolingModelBean } from '@ohos/hvigor';

import { projectOhosConfigManager } from '../../../common/global/project-ohos-config-manager.js';
import { CommonConst } from '../../../const/common-const.js';
import { AppOpt } from '../../../options/build/app-ohos-config.js';
import { AppPlugin } from '../../../plugin/app-plugin.js';
import { OhosPluginId } from '../../../plugin/common/ohos-plugin-id.js';
import { strMapToObj } from '../../../utils/map-util.js';
import { ProjectTaskService } from '../../service/project-task-service.js';
import { projectBuildProfileLoader } from '../../../utils/loader/file/project-build-profile-loader.js';
import { ProjectBuildProfile } from '../../../options/build/project-build-profile.js';
import path from 'path';
import { ModuleModel } from '../../../model/module/module-model.js';
import { GlobalProjectDataService } from '../../service/global-project-data-service.js';

/**
 * OhosProject中的Project模块的toolModel数据模型
 *
 * @since 2022/2/19
 */
export class OhosProjectModelBean implements ToolingModelBean {
  modelId = 'ohos-project';

  private readonly _project: Project;
  private readonly _projectTaskService: ProjectTaskService;

  constructor(project: Project) {
    this._project = project;
    const plugin = project.getPluginById(OhosPluginId.OHOS_APP_PLUGIN) as AppPlugin;
    this._projectTaskService = plugin.getTaskService()!;
  }

  private computeCommonInfo(info: Map<string, any>) {
    const appOptFromConfig: AppOpt = cloneDeep(projectOhosConfigManager.getOverrides()?.appOpt);
    const targetProduct = this._projectTaskService.getTargetProduct();
    const pathInfo = this._projectTaskService.getPathInfo();
    info.set('SELECT_PRODUCT_NAME', targetProduct.name);
    info.set('MODULE_BUILD_DIR', pathInfo.getProjectBuildPath());
    let bundleName = appOptFromConfig?.bundleName ?? targetProduct.bundleName;
    if (bundleName === undefined) {
      bundleName = this._projectTaskService.getProjectModel().getDefaultBundleName();
    }
    info.set('BUNDLE_NAME', bundleName);
  }

  private computePathInfo(info: Map<string, any>) {
    const pathInfo = this._projectTaskService.getPathInfo();
    const buildPath = {
      OUTPUT_PATH: pathInfo.getProjectOutputPath(),
    };
    info.set('BUILD_PATH', buildPath);
  }

  private computeModulesInfo(info: Map<string, any>) {
    const MODULES: ProjectBuildProfile.ModuleBuildOpt[] = cloneDeep(projectBuildProfileLoader.getBuildProfile().modules);
    MODULES.forEach((module) => {
      module.srcPath = path.resolve(this._project.getNodeDir(), module.srcPath);
      module.belongProjectPath = (this._projectTaskService.getProjectModel()?.getSubModuleModels()?.get(module.name) as ModuleModel)?.getBelongProjectPath();
    });
    info.set('MODULES', MODULES);
  }

  private computeProfileOpt(info: Map<string, any>) {
    info.set('PROFILE_OPT', this._projectTaskService.getProjectModel().getProfileOpt());
  }

  /**
   * 计算项目的配置参数：enableSignTask、skipNativeIncremental。
   * @param info
   * @private
   */
  private computeConfigProperties(info: Map<string, any>) {
    info.set('CONFIG_PROPERTIES', hvigorCore.getParameter().getProperties());
  }

  /**
   * 计算工程目录下build-profile.json5里的模块（含外部工程的模块）所属项目的项目路径（所有涉及的项目）
   * 便于子组件在主工程下操作各依赖工程（编译、测试、预览、重载）
   * @param info
   * @private
   */
  private computeOverallProjectPaths(info: Map<string, any>) {
    info.set('OVERALL_PROJECT_PATHS', GlobalProjectDataService.getInstance().getRootPathSet());
  }

  private computeBuildDirInfo(info: Map<string, any>) {
    const buildCacheDir =
      hvigorCore.getExtraConfig().get(CommonConst.BUILD_CACHE_DIR) ??
      HvigorConfigLoader.getInstance().getPropertiesConfigValue<string>(CommonConst.BUILD_DIR_KEY);
    info.set('BUILD_CACHE_DIR', buildCacheDir || '');
  }

  buildModel(): string | undefined {
    const info: Map<string, any> = new Map<string, any>();

    this.computeCommonInfo(info);
    this.computePathInfo(info);
    this.computeModulesInfo(info);
    this.computeProfileOpt(info);
    this.computeConfigProperties(info);
    this.computeOverallProjectPaths(info);
    this.computeBuildDirInfo(info);

    return strMapToObj(info);
  }
}
